<template>
  <p>简单值number: {{count}}</p>
  <p>ref构建对象: {{oCount.n}}</p>
  <p>reactive构建对象: {{state.n + " || " + n}}</p>
  <p>computed总数: {{allCount1 + " || " + allCount2}}</p>
  <p>readonly只读属性: {{copy}}</p>
  <button @click="changeCount(-1)">-1</button> |
  <button @click="changeCount(1)">+1</button>
</template>

<script lang="ts">
import {
  defineComponent,
  watchEffect,
  reactive,
  ref,
  toRefs,
  computed,
  readonly,
  onMounted,
} from "vue";

export default defineComponent({
  name: "c-api-responsive",
  props: {
    point: String,
  },
  /**
   * 初始化props和beforeCreate之间
   * props: 基于Proxy代理的响应式数据
   * NOTICE: props不能在setup参数中解构,解构了就不能再监听变化
   */
  setup(props, context) {
    // 1. ref(一般处理简单值的响应式): 原理还是 defineProperty 监听value的值
    const count = ref<number>(0);
    const oCount = ref<{ n: number }>({ n: 1 });

    // 2. reactive: 基于 Proxy 对数据进行深度的监听
    // 优点: 比Object.defineProperty好处是: 不再有监听缺陷,只要包含在reactive对象内部都可以实现监听
    const state = reactive<{ n: number }>({ n: 2 });

    // 3. computed
    // 只读的
    const allCount1 = computed(() => {
      return count.value + oCount.value.n + state.n;
    });
    // 可更改的
    const allCount2 = computed({
      get: () => count.value + oCount.value.n + state.n,
      set: (val) => {
        // 根据val修改`依赖的值`的数据 -- allCount2.value = 100;//此时val为100
        console.log("allCount2.value = 100", val);
      },
    });
    allCount2.value = 100;

    /**
     * 4. readonly
     * 传入一个对象（响应式或普通）或 ref，返回一个原始对象的只读代理。
     * 一个只读的代理是“深层的”，对象内部任何嵌套的属性也都是只读的。
     * 1.依赖追踪 2.无法直接修改
     */
    const copy = readonly(count);

    /**
     * 对比这种类型的数据修改的方法的区别
     */
    const changeCount = (flag: number) => {
      // count最小值为0
      if (count.value === 0 && flag === -1) return;
      count.value = count.value + flag * 1;
      oCount.value.n = oCount.value.n + flag * 1;
      state.n = state.n + flag * 1;
    };

    onMounted(() => {
      console.log("onMounted!");
      // console.log(context)
      // context.emit("change-second-level", props.point);
    });
    /**
     * 监听route传递过来的Props
     */
    watchEffect(() => {
      console.log("API for Responsive", props);
    });
    return {
      count,
      oCount, // 视图之中不需要.value
      state,
      ...toRefs(state), // 将reactive中每个属性都变成ref响应式数据,再解构成单个ref供视图使用
      allCount1,
      allCount2,
      copy,
      changeCount,
    };
  },
});
</script>
